using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;
using Workflows.Components.ETL.Properties;

namespace Workflows.Components.ETL
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class SyncDbTableComponent : WorkflowComponentBase
    {
        #region props

        private SyncDbTableInstruction _Instruction;
        private SyncDbTableOutput _Output;
        /// <summary></summary>
        public DataProviderType SrcDbProvider
        {
            get { return this._Instruction.SrcDbProvider; }
            set { this._Instruction.SrcDbProvider = value; }
        }
        /// <summary></summary>
        public string SrcConnStr
        {
            get { return this._Instruction.SrcConnStr; }
            set { this._Instruction.SrcConnStr = value; }
        }
        /// <summary></summary>
        public string SrcSchema
        {
            get { return this._Instruction.SrcSchema; }
            set { this._Instruction.SrcSchema = value; }
        }
        /// <summary></summary>
        public string SrcTblName
        {
            get { return this._Instruction.SrcTblName; }
            set { this._Instruction.SrcTblName = value; }
        }
        /// <summary></summary>
        public bool UseSql
        {
            get { return this._Instruction.UseSql; }
            set { this._Instruction.UseSql = value; }
        }
        /// <summary></summary>
        public string SelectStatement
        {
            get { return this._Instruction.SelectStatement; }
            set { this._Instruction.SelectStatement = value; }
        }
        /// <summary></summary>
        public List<string> SrcTableUniqueKeys
        {
            get { return this._Instruction.SrcTableUniqueKeys; }
            set { this._Instruction.SrcTableUniqueKeys = value; }
        }
        /// <summary></summary>
        public string SrcTimeStampField
        {
            get { return this._Instruction.SrcTimeStampField; }
            set { this._Instruction.SrcTimeStampField = value; }
        }
        /// <summary></summary>
        public DataProviderType TgtDbProvider
        {
            get { return this._Instruction.TgtDbProvider; }
            set { this._Instruction.TgtDbProvider = value; }
        }
        /// <summary></summary>
        public string TgtConnStr
        {
            get { return this._Instruction.TgtConnStr; }
            set { this._Instruction.TgtConnStr = value; }
        }
        /// <summary></summary>
        public string TgtTableName
        {
            get { return this._Instruction.TgtTableName; }
            set { this._Instruction.TgtTableName = value; }
        }


        /// <summary></summary>
        public Dictionary<string, string> FieldMappings
        {
            get
            {
                return this._Instruction.FieldMappings;
            }
            set
            {
                this._Instruction.FieldMappings = value;
            }
        }

        public override InstructionBase Instruction
        {
            get { return this._Instruction; }
            set { this._Instruction = (SyncDbTableInstruction) value;}
        }

        public override ResultBase Output
        {
            get { return this._Output; }
            set { this._Output=(SyncDbTableOutput)value; }
        }


        #endregion
        /// <summary></summary>
        public SyncDbTableComponent():base()
        {
            this._Instruction =
                new SyncDbTableInstruction(this.ComponentID, Guid.Empty, 
                    DataProviderType.Oracle, string.Empty, string.Empty,
                                           string.Empty, false, string.Empty, null, string.Empty, DataProviderType.MSSQL,
                                           string.Empty,
                                           string.Empty, null);
            this._Output = new SyncDbTableOutput(this.ComponentID, Guid.Empty, 0);

            this.ComponentName = "Sync Table";
            this.Description = "Synchronize table schema and data between two databases";
            this.ComponentIcon = Resources.ConnWiz30_32512;
            this.ComponentImage = Resources.modemsym_JPG;
            this.ComponentActivityType = WorkflowActivityType.SimpleActivity;
            this.ComponentCategory = WorkflowComponentCategory.ETL.ToString();

        }

        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = base.Serialize(ref xDoc, ref parentNode);

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcDbProvider", ((int) this.SrcDbProvider).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcConnStr", this.SrcConnStr.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcSchema", this.SrcSchema);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcTblName", this.SrcTblName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "UseSql", this.UseSql.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SelectStatement", this.SelectStatement);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcTableUniqueKeys",
                                        StringUtil.ToString(this.SrcTableUniqueKeys == null
                                                                ? null
                                                                :
                                                                    this.SrcTableUniqueKeys.ToArray()));
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcTimeStampField", this.SrcTimeStampField);

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtDbProvider", ((int) this.TgtDbProvider).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtConnStr", this.TgtConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtTableName", this.TgtTableName);
            if (this.FieldMappings != null && this.FieldMappings.Count > 0)
            {
                XmlNode fieldMappingRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "FieldMappings");
                foreach (string srcFieldName in this.FieldMappings.Keys)
                {
                    XmlNode fieldMappingNode = XmlDataUtil.AddElement(ref xDoc, fieldMappingRootNode, "FieldMapping");
                    XmlDataUtil.UpdateAttribute(ref xDoc, fieldMappingNode, "SrcFieldName", srcFieldName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, fieldMappingNode, "TgtFieldName",
                                                this.FieldMappings[srcFieldName]);
                }
            }
            return xNode;
        }

        public override WorkflowComponentBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                SyncDbTableComponent syncTable = base.Instantiate(xNode) as SyncDbTableComponent;

                syncTable.SrcDbProvider =
                    (DataProviderType) int.Parse(xNode.Attributes.GetNamedItem("SrcDbProvider").Value);
                syncTable.SrcConnStr = xNode.Attributes.GetNamedItem("SrcConnStr").Value;
                syncTable.SrcSchema = xNode.Attributes.GetNamedItem("SrcSchema").Value;
                syncTable.SrcTblName = xNode.Attributes.GetNamedItem("SrcTblName").Value;
                syncTable.UseSql = bool.Parse(xNode.Attributes.GetNamedItem("UseSql").Value);
                syncTable.SelectStatement = xNode.Attributes.GetNamedItem("SelectStatement").Value;
                syncTable.SrcTableUniqueKeys = null;
                string[] uniqueKeys = StringUtil.Split(xNode.Attributes.GetNamedItem("SrcTableUniqueKeys").Value);
                if(uniqueKeys !=null && uniqueKeys.Length>0)
                {
                    syncTable.SrcTableUniqueKeys=new List<string>();
                    foreach(string uniqueKey in uniqueKeys)
                    {
                        syncTable.SrcTableUniqueKeys.Add(uniqueKey);
                    }
                }
                syncTable.SrcTimeStampField = xNode.Attributes.GetNamedItem("SrcTimeStampField").Value;

                syncTable.TgtDbProvider =
                    (DataProviderType) int.Parse(xNode.Attributes.GetNamedItem("TgtDbProvider").Value);
                syncTable.TgtConnStr = xNode.Attributes.GetNamedItem("TgtConnStr").Value;
                syncTable.TgtTableName = xNode.Attributes.GetNamedItem("TgtTableName").Value;
                syncTable.FieldMappings = null;
                XmlNodeList fieldMappingNodes = xNode.SelectNodes("FieldMappings/FieldMapping");
                if (fieldMappingNodes != null && fieldMappingNodes.Count > 0)
                {
                    syncTable.FieldMappings = new Dictionary<string, string>();
                    foreach (XmlNode fieldMappingNode in fieldMappingNodes)
                    {
                        string srcFieldName = fieldMappingNode.Attributes.GetNamedItem("SrcFieldName").Value;
                        string tgtFieldName = fieldMappingNode.Attributes.GetNamedItem("TgtFieldName").Value;
                        syncTable.FieldMappings.Add(srcFieldName, tgtFieldName);
                    }
                }

                return syncTable;
            }
            else
                throw new Exception("Unable to instantiate comonent: invalid type specified in xml node");
        }
    }
}
